#ifndef UTILITY_SINGLETON_H
#define UTILITY_SINGLETON_H


#include "assert.h"
#include "Noncopyable.h"

#include <mutex>


template<typename T>
class Singleton final {
    static_assert(sizeof(T), "T must be complete type");

public:
    static T &INSTANCE();

    Singleton() = delete;
    ~Singleton() = default;

private:
    NONCOPYABLE(Singleton);
    
    static void _DESTROY() {
        delete _T;
        _T = nullptr;
    }
    
    static T *_T;
};


template<typename T> T *Singleton<T>::_T = nullptr;

template<typename T>
T &Singleton<T>::INSTANCE() {
    static std::once_flag initFlag{};
    std::call_once(initFlag, [](){
        _T = new T;
        assert(_T);
        ::atexit(_DESTROY);
    });
    return *_T;
}

#endif